Skip to content

Conversation

@dnschneid
Copy link
Contributor

@dnschneid dnschneid commented May 7, 2025

When adaptive clocking is enabled, the MPSSE engine gets blocked waiting for the clock feedback signal to become high. This has a lot of side effects, breaking GPIO accesses, preventing further configuration commands from executing (including both 3-phase clocking as well as disabling adaptive clocking), and confusing the pyftdi read buffer.

The only way to recover seems to be purge the RX buffer, at which point the FTDI will process a "disable adaptive clocking" command.

To avoid getting caught in this condition, only enable adaptive clocking at the start of an I2C transaction and disable it at the end. This helps avoid any additional USB round-trips. If an I2C-related read fails to get any data (mainly when trying to read the ACK bit), assume the bus is wedged, and apply the workaround to ensure adaptive clocking is off until the next attempted I2C transaction.

Tested on an FT4232H. If the DUT is unpowered, GPIO get/set will work normally, and I2C transactions raise I2cIOError/"No answer from FTDI" (unchanged). Once the DUT becomes powered, I2C transactions immediately
work correctly.

@dnschneid
Copy link
Contributor Author

This needs more investigation, unfortunately. Seems that the first byte after power is restored is always reported as a NACK, even when the scope clearly shows it was ACKed.

When adaptive clocking is enabled, the MPSSE engine gets blocked waiting
for the clock feedback signal to become high. This has a lot of side
effects, breaking GPIO accesses, preventing further configuration
commands from executing (including both 3-phase clocking as well as
disabling adaptive clocking), and confusing the pyftdi read buffer.

The only way to recover seems to be purge the RX buffer, at which point
the FTDI will process a "disable adaptive clocking" command.

To avoid getting caught in this condition, only enable adaptive clocking
at the start of an I2C transaction and disable it at the end. This helps
avoid any additional USB round-trips. If an I2C-related read fails to
get any data (mainly when trying to read the ACK bit), assume the bus is
wedged, and apply the workaround to ensure adaptive clocking is off
until the next attempted I2C transaction.

Tested on an FT4232H. If the DUT is unpowered, GPIO get/set will work
normally, and I2C transactions raise I2cIOError/"No answer from FTDI"
(unchanged). Once the DUT becomes powered, I2C transactions immediately
work correctly.
@dnschneid dnschneid force-pushed the dev/david/adaptiveclkcfg branch from 4de5a06 to d9de6b7 Compare May 7, 2025 23:40
@dnschneid dnschneid changed the title Purge RX buffer after enabling/disabling adaptive clock i2c: avoid getting stuck due to adaptive clocking May 7, 2025
@dnschneid
Copy link
Contributor Author

OK, I think I've found the true root issue and worked around it with this PR. Updated the description.

@eblot
Copy link
Owner

eblot commented Aug 14, 2025

Merged with syntax tweak (PEP8 80-col rules) in d8cf514.

Thanks!

@eblot eblot closed this Aug 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants